package com.geotmt.billingcenter.modules.consume.service.impl;

import com.geotmt.billingcenter.common.entry.*;
import com.geotmt.billingcenter.common.enumpackage.ConsumeFeeFlagEnum;
import com.geotmt.billingcenter.common.enumpackage.RuleLabelEnum;
import com.geotmt.billingcenter.common.exception.MyException;
import com.geotmt.billingcenter.common.utils.GeoDateUtils;
import com.geotmt.billingcenter.common.vo.consume.ConsumeHisVo;
import com.geotmt.billingcenter.common.vo.consume.ConsumeVo;
import com.geotmt.billingcenter.common.vo.params.PageOrgFilter;
import com.geotmt.billingcenter.common.vo.params.ParamsConsume;
import com.geotmt.billingcenter.common.vo.params.ParamsForDel;
import com.geotmt.billingcenter.modules.consume.service.*;
import com.geotmt.billingcenter.modules.rules.service.RulesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @Description 消耗 组合 Service
 * @Author      yanghanwei
 * @Mail        yanghanwei@geotmt.com
 * @Date        2019/3/13 14:12
 * @Version     v1
 **/
@Service
@Transactional(rollbackFor = Exception.class)
public class ConsumeServiceImpl extends PageOrgFilter implements ConsumeService {

    private static final Logger logger = LoggerFactory.getLogger(ConsumeServiceImpl.class);

    /**
     * 没有记录需要新增
     */
    private static final String NEW_LIST = "newList";

    /**
     * 有记录但是未生效
     */
    private static final String INVALID_LIST = "invalidList";

    /**
     * 有记录并且已经生效
     */
    private static final String EFFECT_LIST = "effectList";

    /**
     * 不符合添加条件的
     */
    private static final String NOT_FIT_LIST = "notFitList";

    /**
     * 不需要更新的
     */
    private static final String NOT_UPDATE = "notUpdate";

    @Resource
    private ConsumeBaseService consumeBaseService;

    @Resource
    private ConsumeRuleService consumeRuleService;

    @Resource
    private ConsumeBaseHisService consumeBaseHisService;

    @Resource
    private ConsumeRuleHisService consumeRuleHisService;

    @Resource
    private RulesService rulesService;

    @Override
    public void addList(List<ConsumeVo> consumeList) throws Exception{

        logger.info("消耗组合 add service");
        if(null != consumeList && !consumeList.isEmpty()){
            for(ConsumeVo consumeVo : consumeList){
                //添加 有记录已生效的规则
                this.addEffectRule(consumeVo);
            }
        }
    }

    @Override
    public void addUpdateList(List<ConsumeVo> consumeVoList, HttpServletRequest request) throws Exception {
        logger.info("添加或更新消耗规则");
        Map<String, Object> resultMap = this.analyzeList(consumeVoList);
        List<ConsumeVo> newList = (List<ConsumeVo>)resultMap.get(NEW_LIST);
        List<ConsumeVo> invalidList = (List<ConsumeVo>)resultMap.get(INVALID_LIST);
        List<ConsumeVo> effectList = (List<ConsumeVo>)resultMap.get(EFFECT_LIST);
        Integer userId = this.getUserId(request);
        //保存没有记录需要新增的
        if(null != newList && !newList.isEmpty()){
            logger.info("保存没有记录需要新增的，newList：{}",newList);
            for(ConsumeVo vo : newList){
                vo.setCreateTime(new Date());
                vo.setCreateUserId(userId);
                this.addNewRuleSign(vo);
            }
        }
        //修改有记录但未生效的
        if(null != invalidList && !invalidList.isEmpty()){
            logger.info("修改有记录但未生效的，invalidList：{}",invalidList);
            for(ConsumeVo vo : invalidList){
                vo.setUpdateTime(new Date());
                vo.setUpdateUserId(userId);
                this.update(vo);
            }
        }
        //覆盖有记录并且已生效的
        if(null != effectList && !effectList.isEmpty()){
            logger.info("覆盖有记录并且已生效的，effectList：{}",effectList);
            for(ConsumeVo vo : effectList){
                vo.setCreateTime(new Date());
                vo.setCreateUserId(userId);
                this.addEffectRule(vo);
            }
        }
    }

    @Override
    public Map<String, Object> analyzeList(List<ConsumeVo> consumeList) {
        Map<String,Object> resultMap = new HashMap<>(3);
        List<ConsumeVo> newList = new ArrayList<>();
        List<ConsumeVo> invalidList = new ArrayList<>();
        List<ConsumeVo> effectList = new ArrayList<>();
        List<ConsumeVo> notFitList = new ArrayList<>();
        List<ConsumeVo> notUpdate = new ArrayList<>();
        for(ConsumeVo consumeVo : consumeList){
            ParamsConsume params = new ParamsConsume(consumeVo.getProductCode(), consumeVo.getCompanyId(),consumeVo.getCuserId(),consumeVo.getInterfaceId());
            //得到的结果最多只有一个
            List<ConsumeVo> consumeVoList = consumeBaseService.listCurr(params);
            if(null != consumeVoList && !consumeList.isEmpty() && consumeVoList.size() == 1){
                for(ConsumeVo vo : consumeVoList){
                    if(GeoDateUtils.getLongDate(vo.getEffectTime()) - GeoDateUtils.getLongDate(new Date()) >= 0){
                        //有记录但是未生效
                        invalidList.add(consumeVo);
                    }else if(GeoDateUtils.getLongDate(consumeVo.getEffectTime()) - GeoDateUtils.getLongDate(vo.getEffectTime()) == 0){
                        //没有更新的
                        notUpdate.add(consumeVo);
                    }else {
                        //有记录并且已经生效
                        effectList.add(consumeVo);
                    }
                }
            }else{
                //没有记录需要新增
                if(null != consumeVo.getFeeFlag() && null != consumeVo.getEffectTime()){
                    newList.add(consumeVo);
                }else {
                    notFitList.add(consumeVo);
                }
            }
        }
        resultMap.put(NEW_LIST,newList);
        resultMap.put(INVALID_LIST,invalidList);
        resultMap.put(EFFECT_LIST,effectList);
        resultMap.put(NOT_FIT_LIST,notFitList);
        resultMap.put(NOT_UPDATE,notUpdate);
        return resultMap;
    }

    @Override
    public void update(ConsumeVo consumeVo) throws MyException {
        logger.info("消耗组合 update service");
        //0.查询当前记录 是否 已经生效
        ConsumeVo con = consumeBaseService.currGetById(consumeVo.getId());
        long dateYes= System.currentTimeMillis() - 1000L * 60 * 60 * 24;
        if(null != con && GeoDateUtils.getLongDate(con.getEffectTime()) <= GeoDateUtils.getLongDate(new Date(dateYes))){
            throw new MyException("此规则已经生效，不支持修改，请移步至历史规则", HttpServletResponse.SC_NOT_ACCEPTABLE);
        }
        //1.更新curr 中的记录
        ConsumeRuleEntry consumeRule = new ConsumeRuleEntry();
        BeanUtils.copyProperties(consumeVo,consumeRule);
        Integer id = consumeRuleService.addRule(consumeRule);
        if(null != id){
            //2.更新 consume 中的记录
            if(null == consumeVo.getUpdateTime()){
                consumeVo.setUpdateTime(new Date());
            }
            consumeVo.setRId(id);
            consumeBaseService.updateBase(consumeVo);
            //添加阶梯规则
            this.addStairRule(consumeVo,id);
            //更新历史表中有效结束时间
            ParamsConsume params = new ParamsConsume();
            BeanUtils.copyProperties(consumeVo,params);
            List<ConsumeHisVo> consumeHisVos = consumeBaseHisService.listHis(params);
            if(null != consumeHisVos && !consumeHisVos.isEmpty()) {
                consumeBaseHisService.updateEndEffect(GeoDateUtils.getPreDay(consumeVo.getEffectTime(),-1),consumeHisVos.get(0).getId());
            }
        }
    }

    @Override
    public void delete(ParamsForDel obj) throws Exception{
        logger.info("消耗组合 delete service");
        ConsumeVo con = consumeBaseService.currGetById(obj.getId());
        long dateYes= System.currentTimeMillis() - 1000L * 60 * 60 * 24;
        if(null != con && GeoDateUtils.getLongDate(con.getEffectTime()) <= GeoDateUtils.getLongDate(new Date(dateYes))){
            throw new MyException("此规则已经生效，不能删除!", HttpServletResponse.SC_NOT_ACCEPTABLE);
        }
        if(null != obj.getUpdateTime()){
            obj.setUpdateTime(new Date());
        }
        consumeBaseService.deleteBase(obj);
    }

    @Override
    public List<ConsumeVo> list(ParamsConsume paramsConsume) {
        logger.info("消耗 curr list Service");
        return consumeBaseService.listCurr(paramsConsume);
    }

    @Override
    public List<ConsumeVo> listAll(ParamsConsume paramsConsume) {
        logger.info("添加或修改的回显 Service");
        return consumeBaseService.listAll(paramsConsume);
    }

    /**************************************  his  ******************************************/

    @Override
    public void addHis(ConsumeHisVo consumeHisVo) {
        logger.info("历史消耗组合 add service");
        //1.添加历史对象
        //对象复制
        ConsumeRuleHisEntry consumeRuleHis = new ConsumeRuleHisEntry();
        BeanUtils.copyProperties(consumeHisVo,consumeRuleHis);
        Integer id = consumeRuleHisService.addRuleHis(consumeRuleHis);
        if(null != id){
            //对象复制
            ConsumeBaseHisEntry consumeBaseHis = new ConsumeBaseHisEntry();
            BeanUtils.copyProperties(consumeHisVo,consumeBaseHis);
            consumeBaseHis.setRId(id);
            consumeBaseHisService.addBaseHis(consumeBaseHis);
        }
    }

    @Override
    public void updateHis(ConsumeHisVo consumeHisVo) throws Exception {

        //1.根据 要覆盖的开始结束时间 查询His中记录
        ParamsConsume params = new ParamsConsume(consumeHisVo.getProductCode(), consumeHisVo.getCompanyId(), consumeHisVo.getCuserId(), consumeHisVo.getInterfaceId(), consumeHisVo.getEffectStartTime(), consumeHisVo.getEffectEndTime(),"currhis.`effect_start_time`");
        List<ConsumeHisVo> consumeHisList = consumeBaseHisService.listHis(params);

        //2.将list中的记录置为删除状态
        if(null != consumeHisList && !consumeHisList.isEmpty()){
            for(ConsumeHisVo vo : consumeHisList){
                ParamsForDel param = new ParamsForDel(vo.getId(), consumeHisVo.getUpdateUserId(), new Date());
                consumeBaseHisService.deleteBaseHis(param);
            }
        }else{
            throw new MyException("历史中没有相关记录,不符合覆盖修改条件",HttpServletResponse.SC_NOT_ACCEPTABLE);
        }

        //3.切分第一条和最后一条记录并加上覆盖的记录 保存到his中
        List<ConsumeHisVo> listForAdd = new ArrayList<>();
        listForAdd.add(consumeHisVo);

        //不等于0 都要去判断第一个
        if(consumeHisList.size() != 0){
            //3.1.1 判断开始时间是否一致
            if(consumeHisVo.getEffectStartTime().getTime() > consumeHisList.get(0).getEffectStartTime().getTime()){
                ConsumeHisVo consumeHisVo1 = new ConsumeHisVo();
                BeanUtils.copyProperties(consumeHisList.get(0),consumeHisVo1);
                //将时间 减一天 入库
                consumeHisVo1.setEffectStartTime(consumeHisList.get(0).getEffectStartTime());
                consumeHisVo1.setEffectEndTime(GeoDateUtils.getDate(consumeHisVo.getEffectStartTime(),-1));
                consumeHisVo1.setUpdateUserId(consumeHisVo.getUpdateUserId());
                if(null == consumeHisVo1.getUpdateTime()){
                    consumeHisVo1.setUpdateTime(new Date());
                }
                listForAdd.add(consumeHisVo1);
            }
        }

        if(consumeHisList.size() == 1){
            //3.1 size == 1 判断结束时间是否一致
            if(consumeHisVo.getEffectEndTime().getTime() < consumeHisList.get(0).getEffectEndTime().getTime()){
                ConsumeHisVo consumeHisVo1 = new ConsumeHisVo();
                BeanUtils.copyProperties(consumeHisList.get(0),consumeHisVo1);
                //将时间 加一天 入库
                consumeHisVo1.setEffectStartTime(GeoDateUtils.getDate(consumeHisVo.getEffectEndTime(),1));
                consumeHisVo1.setEffectEndTime(consumeHisList.get(0).getEffectEndTime());
                consumeHisVo1.setUpdateUserId(consumeHisVo.getUpdateUserId());
                if(null == consumeHisVo1.getUpdateTime()){
                    consumeHisVo1.setUpdateTime(new Date());
                }
                listForAdd.add(consumeHisVo1);
            }
        }else if(consumeHisList.size() > 1){
            //3.2 size > 1 判断结束时间是否一致
            if(consumeHisVo.getEffectEndTime().getTime() < consumeHisList.get(consumeHisList.size()-1).getEffectEndTime().getTime()){
                ConsumeHisVo consumeHisVo1 = new ConsumeHisVo();
                BeanUtils.copyProperties(consumeHisList.get(consumeHisList.size()-1),consumeHisVo1);
                //将时间 加一天 入库
                consumeHisVo1.setEffectStartTime(GeoDateUtils.getDate(consumeHisVo.getEffectEndTime(),1));
                consumeHisVo1.setEffectEndTime(consumeHisList.get(consumeHisList.size()-1).getEffectEndTime());
                consumeHisVo1.setUpdateUserId(consumeHisVo.getUpdateUserId());
                if(null == consumeHisVo1.getUpdateTime()){
                    consumeHisVo1.setUpdateTime(new Date());
                }
                listForAdd.add(consumeHisVo1);
            }
        }
        //得到新的his list
        for(ConsumeHisVo vo :listForAdd){
            ConsumeRuleHisEntry consumeRuleHis = new ConsumeRuleHisEntry();
            BeanUtils.copyProperties(vo,consumeRuleHis);
            Integer id = consumeRuleHisService.addRuleHis(consumeRuleHis);
            if(null != id){
                vo.setRId(id);
                consumeBaseHisService.addBaseHis(vo);
            }
        }

    }

    @Override
    public void deleteHis(ParamsForDel obj) {
        logger.info("历史消耗组合 delete service");
        consumeBaseHisService.deleteBaseHis(obj);
    }

    @Override
    public List<ConsumeHisVo> listHis(ParamsConsume paramsConsume) {
        logger.info("消耗 his list Service");
        return consumeBaseHisService.listHis(paramsConsume);
    }

    @Override
    public ConsumeHisVo getConsume(String code, Integer companyId, Integer cuserId, Integer interfaceId, Date date) {
        logger.info("获取当前有效的规则 service");
        String dateDay;
        if(null == date){
            date = new Date();
        }
        dateDay = GeoDateUtils.dateStr(date, GeoDateUtils.DATE_FORMAT);
        return consumeBaseService.getConsume(code, companyId, cuserId, interfaceId, dateDay);
    }

    /**
     * 添加阶梯详细规则
     * @param consumeHisVo
     * @param rId
     * @throws Exception
     */
    private void addStairRule(ConsumeHisVo consumeHisVo, Integer rId) throws MyException{
        if(ConsumeFeeFlagEnum.STAIR.value.equals(consumeHisVo.getFeeFlag())){
            List<StairRule> stairRuleList = consumeHisVo.getStairRuleList();
            if(null == stairRuleList){
                throw new MyException("阶梯计费 详细规则不能为空！", HttpServletResponse.SC_NOT_ACCEPTABLE);
            }
            for(StairRule stairRule : stairRuleList){
                stairRule.setRId(rId);
                stairRule.setLabel(RuleLabelEnum.CONSUME_HIS.value);
                rulesService.addStair(stairRule);
            }
        }
    }

    /**
     * 添加阶梯详细规则
     * @param consumeVo
     * @param rId
     * @throws Exception
     */
    private void addStairRule(ConsumeVo consumeVo, Integer rId) throws MyException{
        if(ConsumeFeeFlagEnum.STAIR.value.equals(consumeVo.getFeeFlag())){
            List<StairRule> stairRuleList = consumeVo.getStairRuleList();
            if(null == stairRuleList){
                throw new MyException("阶梯计费 详细规则不能为空！", HttpServletResponse.SC_NOT_ACCEPTABLE);
            }
            for(StairRule stairRule : stairRuleList){
                stairRule.setRId(rId);
                stairRule.setLabel(RuleLabelEnum.CONSUME_CURR.value);
                rulesService.addStair(stairRule);
            }
        }
    }

    /**
     * 保存没有记录需要新增
     * @param consumeVo
     * @throws MyException
     */
    private void addNewRuleSign(ConsumeVo consumeVo) throws MyException {
        logger.info("保存没有记录需要新增的-sub，consumeVo：{}",consumeVo);
        ConsumeRuleEntry consumeRule = new ConsumeRuleEntry();
        BeanUtils.copyProperties(consumeVo,consumeRule);
        Integer id = consumeRuleService.addRule(consumeRule);
        if(null != id){
            ConsumeBaseEntry consumeBase = new ConsumeBaseEntry();
            BeanUtils.copyProperties(consumeVo,consumeBase);
            consumeBase.setRId(id);
            consumeBaseService.addBase(consumeBase);
            //添加 阶梯计费规则
            this.addStairRule(consumeVo,id);
        }
    }

    /**
     * 添加有记录并且已经生效的
     * @param consumeVo     用户传进来的
     * @throws MyException
     */
    private void addEffectRule(ConsumeVo consumeVo) throws MyException {
        logger.info("覆盖有记录并且已经生效的-sub，consumeVo：{}",consumeVo);
        //1.查看精确到接口 维度 是否有记录(产品，客户，用户，接口)
        ParamsConsume params = new ParamsConsume(consumeVo.getProductCode(), consumeVo.getCompanyId(),consumeVo.getCuserId(),consumeVo.getInterfaceId());
        List<ConsumeVo> consumeVoList = consumeBaseService.listCurr(params);
        if(null != consumeVoList && !consumeVoList.isEmpty()){

            //2.1 有记录 就调用删除,并将本记录 添加到 His 中
            for(ConsumeVo consume : consumeVoList){
                long dateYes= System.currentTimeMillis() - 1000L * 60 * 60 * 24;
                //如果未生效的 规则
                if(GeoDateUtils.getLongDate(consume.getEffectTime()) > GeoDateUtils.getLongDate(new Date(dateYes))){
                    throw new MyException("已经有未生效的配置，如需更新请点击更新操作！",HttpServletResponse.SC_NOT_ACCEPTABLE);
                }
                //2.1.1 删除 base
                ParamsForDel params1 = new ParamsForDel(consume.getId(),consumeVo.getCreateUserId(),new Date());
                consumeBaseService.deleteBase(params1);

                //2.1.2 添加 hisRule
                ConsumeRuleHisEntry consumeRuleHis = new ConsumeRuleHisEntry();
                BeanUtils.copyProperties(consume,consumeRuleHis);
                Integer id = consumeRuleHisService.addRuleHis(consumeRuleHis);
                if(id > 0){
                    //2.1.3 添加 hisBase
                    ConsumeHisVo consumeHis = new ConsumeHisVo();
                    BeanUtils.copyProperties(consume,consumeHis);
                    consumeHis.setEffectStartTime(consume.getEffectTime());
                    consumeHis.setEffectEndTime(GeoDateUtils.getDate(consumeVo.getEffectTime(), -1));
                    consumeHis.setUpdateUserId(consumeVo.getCreateUserId());
                    if(null == consumeHis.getCreateTime()){
                        consumeHis.setCreateTime(new Date());
                    }
                    consumeHis.setRId(id);
                    consumeBaseHisService.addBaseHis(consumeHis);
                    //添加 阶梯计费规则
                    this.addStairRule(consumeHis,id);
                }
            }
        }
        //3.添加 规则配置 add base 取到id 之后再添加 consume
        this.addNewRuleSign(consumeVo);
    }

}
